package com.yeyks.app.function.aop;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.yeyks.app.annotation.LoadUserId;
import com.yeyks.app.function.statistical.ManagementStatisticalService;
import com.yeyks.common.em.ResponseStatus;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.commonReference.append.app.TokenService;
import com.yeyks.commonReference.utils.UserUtils;
import com.yeyks.consumer.dal.domain.UserInfo;
import com.yeyks.consumer.service.UserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author fuchangshuai
 * @date 2019/05/15 17:56
 */
@Aspect
@Component
@Slf4j
public class TokenAspect {

    @Autowired
    private TokenService tokenService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private ManagementStatisticalService managementStatisticalService;

    /**
     * 环绕切面
     * 第一个 * 代表任意修饰符及任意返回值
     * 第二个 * 定义在web包或者子包
     * 第三个 * 任意方法 ~ .. 匹配任意数量的参数
     */
    @Before("com.yeyks.app.function.aop.AspectPointcut.webAllController()")
    public void beforMehhod(JoinPoint joinPoint) {
        UserInfo userInfo = null;
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            String token = request.getHeader("headerToken");
            if (StrUtil.isNotBlank(token)) {
                String userId = tokenService.getUserId(token);
                userInfo = userInfoService.getById(Integer.valueOf(userId));
                if (Objects.nonNull(userInfo)) {
                    UserUtils.putLoginUser(userInfo);
                    try {
                        managementStatisticalService.recordUniqueVisitor(userInfo.getId());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
//            if (e instanceof ServiceException) {
//                throw e;
//            }
        }
        try {
            //设置参数里userId的值
            final Object[] argss = joinPoint.getArgs();
            Method method = ((MethodSignature) ((ProceedingJoinPoint) joinPoint).getSignature()).getMethod();
            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
            for (int i = 0; i < parameterAnnotations.length; i++) {
                for (Annotation annotation : parameterAnnotations[i]) {
                    if (annotation instanceof LoadUserId) {
                        if (Objects.isNull(userInfo)) {
                            throw new ServiceException(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode(), "用户信息失效，请重新登录");
                        }
                        ReflectUtil.setFieldValue(argss[i], "userId", userInfo.getId());
                    }
                }
            }
        } catch (Exception e) {
            if (e instanceof ServiceException) {
                throw e;
            }
        }
    }

}
